package com.ck.ips.service.impl.sys;

import com.ck.common.model.Module;
import com.ck.common.model.OperationResult;
import com.ck.core.constant.BusinessConstant;
import com.ck.core.context.UserContextHolder;
import com.ck.core.util.TreeUtils;
import com.ck.ips.dao.sys.ModuleMapper;
import com.ck.ips.model.dto.sys.ModuleDTO;
import com.ck.ips.service.sys.ModuleService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 模块Service实现类
 *
 */
@Service(value = "moduleService")
public class ModuleServiceImpl implements ModuleService {
	@Autowired
	private ModuleMapper moduleMapper;
	/** 菜单资源名称最大长度 */
	private final int MAX_MODULE_NAME_LENGTH = 8;
	/**
	 * 保存模块
	 *
	 * @param module Module
	 */
	@Override
	@Transactional( rollbackFor = Exception.class)
	public OperationResult saveModule(Module module){
		if (module == null || StringUtils.isBlank(module.getModuleName())) {
			return OperationResult.newValidateFailOperationResult("输入参数不能为空");
		}
		if ( module.getModuleName().length() > MAX_MODULE_NAME_LENGTH) {
			return OperationResult.newValidateFailOperationResult("菜单或按钮名称长度不能超过"+ MAX_MODULE_NAME_LENGTH +"位");
		}
		if ( module.getStatus() == null ) {
			return OperationResult.newValidateFailOperationResult("菜单状态不能为空");
		}
		//检查名称是否重复
		Module nameModule = getModuleByModuleName(module.getModuleName());
		if (nameModule != null) {
			return OperationResult.newValidateFailOperationResult("资源名称已存在");
		}
		module.setAddTime(System.currentTimeMillis());
		module.setOperator(UserContextHolder.currentUser().getUserName());
		moduleMapper.insertModule(module);
		return OperationResult.newSuccessTipsOperationResult("添加模块:" + module.getModuleName());
	}

	/**
	 * 通过ID更新模块
	 *
	 * @param module Module
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public OperationResult updateModule(Module module){
		if (module == null || module.getModuleId() == null || StringUtils.isBlank(module.getModuleName())) {
			return OperationResult.newValidateFailOperationResult("输入参数不能为空");
		}
		if ( module.getModuleName().length() > MAX_MODULE_NAME_LENGTH) {
			return OperationResult.newValidateFailOperationResult("菜单或按钮名称长度不能超过"+ MAX_MODULE_NAME_LENGTH +"位");
		}
		if ( module.getStatus() == null ) {
			return OperationResult.newValidateFailOperationResult("菜单状态不能为空");
		}
		Module oldModule = moduleMapper.getByModuleId(module.getModuleId());
		if ( oldModule == null ) {
			return OperationResult.newValidateFailOperationResult("操作的模块不存在");
		}
 		//检查名称是否重复
		Module nameModule = getModuleByModuleName(module.getModuleName());
		if (nameModule != null && !nameModule.getModuleId().equals(module.getModuleId())) {
			return OperationResult.newValidateFailOperationResult("模块资源名称已存在");
		}
		module.setOperator(UserContextHolder.currentUser().getUserName());
		module.setUpdateTime(System.currentTimeMillis());
		moduleMapper.updateModuleById(module);
		return OperationResult.newSuccessTipsOperationResult("修改模块：" + module.getModuleName());
	}

	/**
	 * 通过模块名称获取模块
	 *
	 * @param moduleName 模块名称
	 * @return Module
	 */
	@Override
	public Module getModuleByModuleName(String moduleName){
		return moduleMapper.getModuleByModuleName(moduleName);
	}

	/**
	 * 获取模块的子模块
	 *
	 * @param moduleId 模块ID
	 * @return List<ModuleDTO>
	 */
	@Override
	public List<ModuleDTO> listChildrenModule(Long moduleId){
		return moduleMapper.listChildrenModule(moduleId);
	}

	/**
	 * 通过模块ID获取角色ID列表
	 *
	 * @param moduleId 模块ID
	 * @return List<Long>
	 */
	@Override
	public List<Long> listRoleIdsFromRoleModuleByModuleId(Long moduleId){
		return moduleMapper.listRoleIdsFromRoleModuleByModuleId(moduleId);
	}

	/**
	 * 通过模块ID删除模块
	 *
	 * @param moduleId 模块ID
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public OperationResult deleteModuleById(Long moduleId){
		if (moduleId == null) {
			return OperationResult.newValidateFailOperationResult("模块ID不能为空");
		}
		Module oldModule = moduleMapper.getByModuleId(moduleId);
		if ( oldModule == null ) {
			return OperationResult.newValidateFailOperationResult("操作的模块不存在");
		}
		//检查模块是否有子模块，如果有，不能删除
		List<ModuleDTO> moduleDTOList = listChildrenModule(moduleId);
		if (CollectionUtils.isNotEmpty(moduleDTOList)) {
			return OperationResult.newValidateFailOperationResult("该模块有子模块，请先删除该模块的子模块");
		}
		//检查模块是否与角色关联，如果有，不能删除
		List<Long> roleIdList = listRoleIdsFromRoleModuleByModuleId(moduleId);
		if (CollectionUtils.isNotEmpty(roleIdList)) {
			return OperationResult.newValidateFailOperationResult("该模块已关联角色，请先解除与角色的关联");
		}
		//删除模块
		moduleMapper.deleteModuleById(moduleId);
		return OperationResult.newSuccessTipsOperationResult("删除模块：" + oldModule.getModuleName());
	}

	/**
	 * 获取角色拥有的菜单模块
	 *
	 * @return List<ModuleDTO>
	 */
	@Override
	public List<ModuleDTO> getMenuByRoleId(Long roleId,boolean buildTree) {
		List<ModuleDTO> moduleList = moduleMapper.listAllEnableModule();
		if (CollectionUtils.isEmpty(moduleList)) {
			return new ArrayList<>();
		}
		//查找角色相关的权限
		if (roleId != null) {
			List<String> moduleIdList = moduleMapper.listModuleIdsByRoleId(roleId);
			if (CollectionUtils.isNotEmpty(moduleIdList)) {
				for (String strModuleId : moduleIdList) {
					if (StringUtils.isBlank(strModuleId)) {
						continue;
					}
					for (ModuleDTO module : moduleList) {
						Long moduleId = module.getModuleId();
						if (moduleId == null) {
							continue;
						}
						if (strModuleId.equals(String.valueOf(moduleId))) {
							module.setChecked(true);
							break;
						}
					}
				}
			}
		}
		return buildTree ? TreeUtils.getTreeList(moduleList) : moduleList;
	}

	/**
	 * 获取用户所拥有的菜单模块
	 *
	 * @return List<MenuModuleDTO>
	 */
	@Override
	public Map<String,List<ModuleDTO>> getUserResources(){
		Map<String,List<ModuleDTO>> dataMap = new HashMap<>();
		List<ModuleDTO> moduleList = listModuleByUser();
		if ( CollectionUtils.isNotEmpty(moduleList) ) {
			List<ModuleDTO> menu = moduleList.stream().filter( e -> BusinessConstant.TYPE_MENU.equals(e.getType())).collect(Collectors.toList());
			List<ModuleDTO> button = moduleList.stream().filter( e -> BusinessConstant.TYPE_BUTTON.equals(e.getType())).collect(Collectors.toList());
			dataMap.put("menu",TreeUtils.getTreeList(menu));
			dataMap.put("button",button);
			return dataMap;
		}
		return Collections.EMPTY_MAP;
	}

	@Override
	public List<ModuleDTO> listModuleByUser() {
		List<ModuleDTO> moduleList;
		if ( UserContextHolder.currentUser().isSuper() ) {
			moduleList = moduleMapper.listAllEnableModule();
		} else {
			moduleList = moduleMapper.listMenuModuleByUserId(UserContextHolder.currentUser().getUserId());
		}
		return moduleList;
	}

	@Override
	public List<ModuleDTO> listMenuByUserId(Long userId,boolean superUser) {
		List<ModuleDTO> moduleList;
		if ( superUser ) {
			moduleList = moduleMapper.listAllEnableModule();
		} else {
			moduleList = moduleMapper.listMenuModuleByUserId(userId);
		}
		if ( CollectionUtils.isNotEmpty(moduleList) ) {
			return TreeUtils.getTreeList(moduleList.stream().filter( e -> BusinessConstant.TYPE_MENU.equals(e.getType())).collect(Collectors.toList()));
		}
		return Collections.EMPTY_LIST;
	}

	@Override
	public List<ModuleDTO> listAllModule(boolean buildTree) {
		List<ModuleDTO> allModule = moduleMapper.listAllModule();
		if ( CollectionUtils.isNotEmpty(allModule) ) {
			return buildTree ? TreeUtils.getTreeList(allModule) : allModule;
		}
		return new ArrayList<>();
	}

	@Override
	public boolean resourceMatch(String resource) {
		// todo 当前为每次访问实时请求数据库判断，应考虑加入缓存优化
		if ( StringUtils.isBlank(resource) ) {
			return false;
		}
		List<ModuleDTO> resources = listModuleByUser();

		ModuleDTO module = null;
		if ( resources != null ) {
			for (ModuleDTO e :resources) {
				if (resource.equals(e.getUrl())) {
					module = e;
					break;
				}
			}
		}
		return resources != null && module != null;
	}

}
